package unwdmi.db;

import java.net.*;
import java.util.*;

import unwdmi.dto.StationDTO;

import com.mongodb.*;
import com.mongodb.util.*;

/**
 * @class MongoDB
 * @author Michel Jansma
 * Connect to MongoDB 
 */
public class MongoDB {

	private MongoClient client;
	private DB mongoDB;
	private ArrayList<ServerAddress> hosts;
	
	private HashMap<String,DBCollection> collections;
	private Map<Integer,StationDTO> stations = new HashMap<Integer,StationDTO>();
	
	/**********************
	 *** GLOBAL METHODS ***
	 *********************/
	
	public MongoDB() {
		
		this.hosts = new ArrayList<ServerAddress>();
		this.collections = new HashMap<String,DBCollection>();
		this.setHost("localhost",27017);
		this.setHost("localhost",37017);
		this.setHost("localhost",47017);
		this.setMongoClient();
		this.setMongoDB("UNWDMI");
		this.setCollection("measurements");
		this.setCollection("stations");
		this.setStations();
		
		//this.getCollection("measurements").drop();
		
		//*************** TMP ***************
		
		System.out.println("MONGO_MEASUREMENTS : " + this.getCollection("measurements").getCount());
		System.out.println("MONGO_STATIONS     : " + this.getCollection("stations").getCount());
		
	};
	
	private void setCollection(String name) {
		this.collections.put(name, this.mongoDB.getCollection(name));
	};
	
	public DBCollection getCollection(String name) {
		return this.collections.get(name);
	};
	
	/**********************
	 *** SETTER METHODS ***
	 *********************/
	
	private void setMongoClient() {
		this.client = new MongoClient(this.hosts);
		this.client.setReadPreference(ReadPreference.secondaryPreferred());
	};
	
	private void setHost(String host, int port) {
		try {
			this.hosts.add(new ServerAddress(host,port));
		} catch(UnknownHostException e) {
			e.printStackTrace();
		};
	};
	
	/**
	 * @method setStations
	 * Store all station from MongoDB
	 */
	private void setStations() {
		DBCursor cursor = this.getCollection("stations").find();
		StationDTO station;
		DBObject object;
		while(cursor.hasNext()) {
			object = cursor.next();
			station = new StationDTO(
				Integer.parseInt(object.get("ID").toString()),
				Double.parseDouble(object.get("LONGITUDE").toString()),
				Double.parseDouble(object.get("LATITUDE").toString()),
				Double.parseDouble(object.get("ELEVATION").toString()),
				String.valueOf(object.get("NAME")),
				String.valueOf(object.get("COUNTRY"))
			);
			this.stations.put(station.getID(), station);
		};
	};
	
	/**********************
	 *** GETTER METHODS ***
	 *********************/
	
	private void setMongoDB(String dbname) {
		this.mongoDB = this.client.getDB(dbname);
	};
	
	public DB getMongoDB() {
		return this.mongoDB;
	};	
	
	public StationDTO getStation(Integer id) {
		return this.stations.get(id);
	};
	
	//CREATE//
	
	private WriteResult createObject(String collection, DBObject object) {
		return this.getCollection(collection).insert(object);
	};
	
	public WriteResult createMeasurement(String json) {
		return this.createObject("measurements", (DBObject)JSON.parse(json));
	};
	
	public WriteResult createStation(String json) {
		return this.createObject("stations", (DBObject)JSON.parse(json));
	};
	
	//READ//
	
	public DBCursor readMeasurements(String key, String value) {
		return this.getCollection("measurements").find(new BasicDBObject(key,value));
		//TODO complete
	};
	
	public DBCursor readStations(String key, String value) {
		return this.getCollection("stations").find(new BasicDBObject(key,value));
		//TODO complete
	};
	
	
}
